#ifndef __TUPLE_HPP__
#define __TUPLE_HPP__

#include "math/math_config.h"
#include <memory.h>
#include "math/math_op.h"


NS_MATH_BEGIN

template<typename T, int _N>
class tuple
{
public:
	typedef T value_type;
	typedef T& reference;
	typedef const T& const_reference;
	typedef tuple<T,_N> this_type;
	typedef unsigned int size_type;

	static const size_type DIM = _N;

protected:
	value_type m_data[_N];

public:
	tuple()
	{
		for(auto i=0;i<DIM;++i)m_data[i] = value_type();
	}
	tuple(const this_type& tup)
	{
		memcpy(m_data, tup.m_data, DIM*sizeof(value_type));
	}

	tuple(value_type a){m_data[0]=a;}
	tuple(value_type a, value_type b){m_data[0]=a;m_data[1]=b;}
	tuple(value_type a, value_type b, value_type c){m_data[0]=a;m_data[1]=b;m_data[2]=c;}
	tuple(value_type a, value_type b, value_type c, value_type d)
	{
		m_data[0] = a; m_data[1] = b;
		m_data[2] = c; m_data[2] = d;
	}


public:
	reference operator[] (size_t idx){return m_data[idx];}
	const_reference operator[] (size_t idx)const{return m_data[idx];}

	this_type& operator= (const this_type& tup)
	{
		memcpy(m_data, tup.m_data, DIM*sizeof(value_type));
		return *this;
	}

	inline size_type size()const{return DIM;}

public:
	// OPERATORS

	OP1(+=);
	OP1(-=);
	OP1(*=);
	OP1(/=);
	
	OP2(+,+=);
	OP2(-,-=);
	OP2(*,*=);
	OP2(/,/=);

public:
	template<typename XOP>
	void accept(XOP& op)
	{
		for(reference x:m_data)
		{
			op.g(x);
		}
	}
};




NS_MATH_END

#endif